package com.thinkit.security.custom;
import com.thinkit.core.handler.CustomException;
import com.thinkit.utils.utils.Checker;
import org.springframework.dao.QueryTimeoutException;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

@Component
public class CustomUserAuthenticationProvider extends CustomUserAuthenticationBaseProvider implements AuthenticationProvider {

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String password = authentication.getCredentials().toString();
        UserDetails user;
        try {
            user = loadUserByUsername(authentication);
        } catch (UsernameNotFoundException | CustomException | LockedException e){
            throw new CustomException(e.getMessage(), HttpStatus.FORBIDDEN.value());
        }catch (RedisConnectionFailureException| QueryTimeoutException e) {
            throw new CustomException("请核查 redis 服务连接是否正常", HttpStatus.SERVICE_UNAVAILABLE.value());
        }catch (Exception e) {
            String errMsg = Checker.BeNotNull(e.getCause())?e.getCause().getMessage():e.getMessage();
            throw new CustomException(errMsg, HttpStatus.FORBIDDEN.value());
        }
        return new UsernamePasswordAuthenticationToken(user, password, user.getAuthorities());
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return aClass.equals(UsernamePasswordAuthenticationToken.class);
    }
}
